package redis

import (
	"auth/model"
	"context"
	"crypto/md5"
	"encoding/base64"
	"fmt"
	"time"
)

func NewUser() *user {
	return &user{}
}

var UserRedis = NewUser()

type user struct{}

var (
	prefix    = "ebike:auth"
	smsPrefix = "manager:value:ebike:manager"
)

func (u *user) userTokenKey(userId int64) string {
	return fmt.Sprintf("%s:%s:%v", prefix, "userToken", userId)
}
func (u *user) userLoginFailedCountKey(userId int64) string {
	return fmt.Sprintf("%s:%s:%v", prefix, "userLogin", userId)
}
func (u *user) smsKey(phone string) string {
	return fmt.Sprintf("%s:%s:%v", smsPrefix, "sms", phone)
}

// SetToken 设置token 有过期时间
func (u *user) SetToken(ctx context.Context, userId int64, token string) error {
	var (
		err error
	)

	// md5 加密
	hash := md5.New()
	hash.Write([]byte(token))
	bytes := hash.Sum(nil)
	key := base64.URLEncoding.EncodeToString(bytes)
	_, err = KV.SetEX(ctx, u.userTokenKey(userId), key, model.TokenExpTime).Result()
	return err

}

// ExistsToken token是否存在
func (u *user) ExistsToken(ctx context.Context, userId int64, token string) bool {

	// md5 加密
	hash := md5.New()
	hash.Write([]byte(token))
	bytes := hash.Sum(nil)
	md5Str := base64.URLEncoding.EncodeToString(bytes)

	val := KV.Get(ctx, u.userTokenKey(userId)).Val()
	if val == md5Str {
		return true
	}
	return false
}

// DeleteToken 用户登出 删除token
func (u *user) DeleteToken(ctx context.Context, userId int64) error {
	return KV.Del(ctx, u.userTokenKey(userId)).Err()
}

// GetLoginCount 获取登陆错误次数
func (u *user) GetLoginCount(ctx context.Context, userId int64) string {

	val := KV.Get(ctx, u.userLoginFailedCountKey(userId)).Val()

	return val
}

// CheckVerificationCode 检查验证码
func (u *user) CheckVerificationCode(ctx context.Context, phone, code string) bool {
	val := KV.Get(ctx, u.smsKey(phone)).Val()
	if val == code {
		return true
	}
	return false
}

// DeleteVerificationCode 删除验证码
func (u *user) DeleteVerificationCode(ctx context.Context, phone string) error {
	return KV.Del(ctx, u.smsKey(phone)).Err()
}

func (u *user) LoginActive(ctx context.Context, user int64) error {
	return KV.SetBit(ctx, fmt.Sprintf("%s:%s:%s:%s", prefix, "user", "active", time.Now().Format("2006-01-02")), user, 1).Err()
}

func (u *user) GetActiveUserCount(ctx context.Context, key string) (int64, error) {
	key = fmt.Sprintf("%s:%s:%s:%s", prefix, "user", "active", key)
	return KV.BitCount(ctx, key, nil).Result()
}

func (u *user) GetOriginCountBits(ctx context.Context, key string) (string, error) {
	key = fmt.Sprintf("%s:%s:%s:%s", prefix, "user", "active", key)
	result, err := KV.Get(ctx, key).Result()
	if err != nil {
		return "", err
	}
	return result, err
}

func (u *user) TryLock(ctx context.Context, key string) bool {
	// 1 表示存在
	key = fmt.Sprintf("%s:%s:%s:%s", prefix, "user", "active", key)
	return KV.SetNX(ctx, key, "1", time.Second*10).Val()
}

func (u *user) SetLoginToken(ctx context.Context, uid int64, token string, expire time.Duration) error {
	key := fmt.Sprintf("%s:%s:%s:%d", prefix, "user", "token", uid)
	return KV.SetEX(ctx, key, token, expire).Err()
}

func (u *user) GetLoginToken(ctx context.Context, uid int64) (string, error) {
	key := fmt.Sprintf("%s:%s:%s:%d", prefix, "user", "token", uid)
	return KV.Get(ctx, key).Result()
}
